package com.mhz.cae;

import java.util.ArrayList;
import java.util.List;

import org.anddev.andengine.engine.Engine;
import org.anddev.andengine.engine.camera.Camera;
import org.anddev.andengine.engine.camera.hud.HUD;
import org.anddev.andengine.engine.options.EngineOptions;
import org.anddev.andengine.engine.options.EngineOptions.ScreenOrientation;
import org.anddev.andengine.engine.options.resolutionpolicy.RatioResolutionPolicy;
import org.anddev.andengine.entity.scene.Scene;
import org.anddev.andengine.entity.scene.Scene.IOnSceneTouchListener;
import org.anddev.andengine.entity.scene.background.ColorBackground;
import org.anddev.andengine.entity.util.FPSLogger;
import org.anddev.andengine.extension.input.touch.controller.MultiTouch;
import org.anddev.andengine.extension.input.touch.exception.MultiTouchException;
import org.anddev.andengine.extension.physics.box2d.FixedStepPhysicsWorld;
import org.anddev.andengine.extension.physics.box2d.PhysicsWorld;
import org.anddev.andengine.input.touch.TouchEvent;
import org.anddev.andengine.opengl.font.Font;
import org.anddev.andengine.opengl.texture.TextureOptions;
import org.anddev.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlas;
import org.anddev.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlasTextureRegionFactory;
import org.anddev.andengine.ui.activity.BaseGameActivity;

import android.graphics.Color;
import android.graphics.Typeface;
import android.hardware.SensorManager;

import com.badlogic.gdx.math.Vector2;
import com.mhz.cae.events.AddItemEvent;
import com.mhz.cae.events.Event;
import com.mhz.cae.events.EventManager;
import com.mhz.cae.events.Listener;
import com.mhz.cae.events.SelectItemEvent;
import com.mhz.cae.hud.Inventory;
import com.mhz.cae.hud.OpenInventoryButton;
import com.mhz.cae.hud.PlayButton;
import com.mhz.cae.hud.TrashButton;
import com.mhz.cae.level.Level;
import com.mhz.cae.level.Level0;
import com.mhz.cae.objects.Item;
import com.mhz.cae.objects.ItemType;
import com.mhz.cae.objects.SoccerBall;
import com.mhz.cae.objects.TennisBall;
import com.mhz.cae.objects.Trampoline;
import com.mhz.cae.util.MultiTouchDetector;
import com.mhz.cae.util.MultiTouchDetector.IMultiTouchDetectorListener;

public class CausesAndEffectsActivity extends BaseGameActivity implements IOnSceneTouchListener, IMultiTouchDetectorListener, Listener {

	// Constants
	public static final int CAMERA_WIDTH = 800;
	public static final int CAMERA_HEIGHT = 480;

	// Fields
	private BitmapTextureAtlas mHudTextureAtlas;
	private BitmapTextureAtlas mObjectsTextureAtlas;
	private BitmapTextureAtlas mFontTexture;
	private Font mFont;

	private Camera mCamera;
	private Scene mScene;
	private PhysicsWorld mPhysicsWorld;
	private MultiTouchDetector mRotateDetector;

	private static Inventory mInventory;

	private static Level mLevel;

	private static List<Item> mItems = new ArrayList<Item>();
	private TrashButton trashButton;
	private Item currentItem = null;

	@Override
	public Engine onLoadEngine() {
		// Init the camera
		mCamera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);

		// Create AndEngine options
		final EngineOptions engineOptions = new EngineOptions(true, ScreenOrientation.LANDSCAPE, new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT),
				mCamera);
		engineOptions.getTouchOptions().setRunOnUpdateThread(true);

		// Load AndEngine
		return new Engine(engineOptions);
	}

	@Override
	public void onLoadResources() {
		// Load texture atlas
		this.mObjectsTextureAtlas = new BitmapTextureAtlas(128, 256, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
		this.mHudTextureAtlas = new BitmapTextureAtlas(128, 128, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
		BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");

		// TODO Load fonts better
		this.mFontTexture = new BitmapTextureAtlas(256, 256, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
		this.mFont = new Font(this.mFontTexture, Typeface.create(Typeface.DEFAULT, Typeface.BOLD), 16, true, Color.WHITE);
		this.mEngine.getTextureManager().loadTexture(this.mFontTexture);
		this.mEngine.getFontManager().loadFont(this.mFont);

		// Load HUD resource
		OpenInventoryButton.loadResource(getApplicationContext(), this.mHudTextureAtlas);
		PlayButton.loadResource(getApplicationContext(), this.mHudTextureAtlas);
		TrashButton.loadResource(getApplicationContext(), this.mHudTextureAtlas);

		// Load objects textures
		TennisBall.loadResource(getApplicationContext(), this.mObjectsTextureAtlas);
		SoccerBall.loadResource(getApplicationContext(), this.mObjectsTextureAtlas);

		// Add textures to engine
		this.mEngine.getTextureManager().loadTexture(this.mObjectsTextureAtlas);
		this.mEngine.getTextureManager().loadTexture(this.mHudTextureAtlas);
	}

	@Override
	public Scene onLoadScene() {
		// Create and init the scene
		this.mScene = new Scene();
		this.mScene.setBackground(new ColorBackground(0, 0, 0));
		this.mScene.setOnSceneTouchListener(this);
		this.mScene.setTouchAreaBindingEnabled(true);
		this.mScene.setOnAreaTouchTraversalFrontToBack();

		// Create the physic world
		this.mPhysicsWorld = new FixedStepPhysicsWorld(30, new Vector2(0, 0), false, 3, 2);

		// Add multitouch
		if (MultiTouch.isSupportedByAndroidVersion()) {
			try {
				this.mRotateDetector = new MultiTouchDetector(this);
			} catch (final MultiTouchException e) {
				this.mRotateDetector = null;
			}
		} else {
			this.mRotateDetector = null;
		}

		// Add update handlers
		this.mEngine.registerUpdateHandler(new FPSLogger());
		this.mScene.registerUpdateHandler(this.mPhysicsWorld);

		// Add level static elements
		mLevel = Level0.createLevel(this.mPhysicsWorld, this.mScene);

		// Add HUD elements
		final HUD hud = new HUD();
		PlayButton playButton = PlayButton.createButton(10, 10);
		playButton.init(hud);
		OpenInventoryButton addButton = OpenInventoryButton.createButton(CAMERA_WIDTH - 60, 10);
		addButton.init(hud);
		trashButton = TrashButton.createButton(CAMERA_WIDTH - 118, 10);
		trashButton.init(hud);
		// Create inventory
		mInventory = Inventory.createInventory(hud);
		mInventory.setItems(mLevel.getAvailableItems());
		mInventory.initItems(mFont, hud);

		mCamera.setHUD(hud);

		// Return the scene
		return this.mScene;
	}

	@Override
	public void onLoadComplete() {
		EventManager.getInstance().registerListener(this);
		this.mEngine.registerUpdateHandler(EventManager.getInstance());
	}

	@Override
	public boolean onSceneTouchEvent(final Scene pScene, final TouchEvent pSceneTouchEvent) {
		if (this.mRotateDetector != null) {
			this.mRotateDetector.onTouchEvent(pSceneTouchEvent);
		}
		return true;
	}

	@Override
	public void processEvent(Event event) {
		switch (event.getType()) {
		case LAUNCH_EVENT:
			mInventory.hide();
			launch();
			break;
		case RESET_EVENT:
			reset();
			break;
		case OPEN_INVENTORY_EVENT:
			mInventory.openClose();
			break;
		case ADD_ITEM_EVENT:
			mInventory.hide();
			ItemType itemType = ((AddItemEvent) event).getAddedItem();
			if (itemType != null) {
				addItem(itemType.createItem());
			}
			break;
		case SELECT_ITEM_EVENT:
			selectItem(((SelectItemEvent) event).getSelectedItem());
			break;
		}
	}

	private void launch() {
		this.mPhysicsWorld.setGravity(new Vector2(0, SensorManager.GRAVITY_EARTH));
	}

	private void reset() {
		this.mPhysicsWorld.setGravity(new Vector2(0, 0));
		mLevel.resetLevel();
		for (Item item : mItems) {
			item.resetObject();
		}
	}

	private void addItem(Item item) {
		if (item != null) {
			item.initObject(this.mPhysicsWorld, this.mScene);
			if (item instanceof Trampoline) {
				((Trampoline) item).registerTrashable(this.mPhysicsWorld, this.mScene, this.trashButton.getFace());
			}
			selectItem(item);
			mItems.add(item);
		}
	}

	private void selectItem(final Item item) {
		item.setSelected(true);
		if (currentItem != null) {
			currentItem.setSelected(false);
		}
		currentItem = item;

	}

	@Override
	public boolean isDestroyed() {
		return false;
	}

	@Override
	public void onTouchStarted(MultiTouchDetector pRotateDetector, TouchEvent pSceneTouchEvent) {
	}

	@Override
	public void onTouchMotion(MultiTouchDetector pRotateDetector, TouchEvent pTouchEvent, float pZoomFactor, float pAngle) {
		if (currentItem != null) {
			currentItem.transform(mPhysicsWorld, pZoomFactor, pAngle);
		}
	}

	@Override
	public void onTouchFinished(MultiTouchDetector pRotateDetector, TouchEvent pTouchEvent, float pZoomFactor, float pAngle) {
		if (currentItem != null) {
			currentItem.transform(mPhysicsWorld, pZoomFactor, pAngle);
		}
	}

}